#!/usr/bin/python
# -*- coding: UTF-8 -*-
'''
支持如下命令
1、在*.py当前目录生成版本号.c文件: 
    *.py
2、在指定路径生成版本号.c文件: 
    *.py -v path/*.c
3、在bin文件后加入版本号: 
    *.py -n path/*.bin
4、生成带前缀的升级文件, 并在文件名后加入版本号, alias为生成文件别名, alias非空按别名生成文件: 
    *.py -u path/src.bin alias
5、生成带前缀的升级文件, 并在文件名后加入版本号, 根据偏移offset, 合并boot和app文件, alias为生成文件别名, alias非空按别名生成文件: 
    *.py -um path/boot.bin offset path/app.bin alias
    
    python3 ../tools/version_tool.py -v ../User/app
    IAR:
        python3 ../tools/version_tool.py -u  $TARGET_DIR$/XXX.bin
        python3 ../tools/version_tool.py -um ../tools/boot.bin 0x10000 $TARGET_DIR$/XXX.bin
    atollic:
        python3 ../tools/version_tool.py -n "${BuildArtifactFileBaseName}.hex" 
'''
import time
import os
import sys
from ast import literal_eval
import struct
import zlib

argc =  len(sys.argv)
argv = sys.argv

#print ('argc:', argc)
#print ('argv:', argv)

print(argv)

#path = os.getcwd()
path= "."

version = "0"
log = open('log.txt', "w+")
for i in argv:
    log.write(i+' ')
log.write('\n')
#log.close()

def git_version():
    command  = "git describe --tags --always --dirty=\"-dirty\" "
    #print(command)
    log = os.popen(command)
    ret = log.read()
    log.close()
    #print("git msg:", ret)
    #print("git msg len:", len(ret))
    if(len(ret) == 0):
        return -1
    v=ret.find("fatal: not a git repository")
    #print("****:",v)
    if(v == -1):
        #print("git version:", ret)
        global version
        temp=ret.split("\n")
        version=temp[0]
        return 0
    else:
        return -1

def svn_version():
    offset=argv[0].rfind('/')
    path=argv[0][0:offset]+'/..'
    command  = "svn log -l 1 " + path
    #print(command)
    _msg = os.popen(command)
    ret = _msg.read()
    _msg.close()
    #print(ret)
    #print("svn log msg length:", len(ret))
    if(len(ret) == 0):
        return -1
    '''
    print(ret.find("is not a working copy"))
    if(ret.find("is not a working copy") != -1):
        return -1
    '''
    #print(ret.find("----"))
    if(ret.find("----") == -1):
        return -1
    list=ret.split()
    ret = list[1]
    #print(ret)
    index=ret.index("r")
    #print("r index:", index)
    global version
    version=ret#[index+1:]
    #print(version)
    command  = "svn st -qu " + path
    #print(command)
    log = os.popen(command)
    ret=log.read()
    #print("read len:", len(ret))
    log.close()

    if(len(ret) == 0):
        pass
    else :
        version = version + "M"
        #print("svn version:", version)
    


def get_verion():
    ret = svn_version()
    if(ret != -1):
        pass
    else:
        ret = git_version()

def generate_version_c(path):
    try:
        if(path == ""):
            path = "_version_.c"
        print("version file :", path)
        fo = open(path, "r")
        temp = fo.read()
        fo.close()
        #print(temp)
        offset = temp.find(version)
        old = temp[offset:]
        offset = old.find("\"")
        old = old[0:offset]
        #print("old ver:", ver)
        if(old == version):
            print("vesion file is the same, exit")
            return
        else:
            print("version file is changed, update")
            pass
    except:
        pass
    
    fo = open(path, "w+")
    name = argv[0].split("/")
    msg="/**\n"
    msg=msg+"*This file is automatic generated by "+name[-1]+"\n"
    msg=msg+"*/\n\n"
    msg=msg+"const char *get_verstring(void)\n"
    msg=msg+"{\n"
    msg=msg+"\treturn \"" + version +"\";\n"
    msg=msg+"};\n"
    #print(msg)
    fo.write(msg)
    fo.close()
    print("generate version c file success!")
    log.write("generate version c file success!\n")
if __name__ == "__main__":
    get_verion()
    opt=0
    boot_name = ""
    app_name =  ""
    app_offset= 0xc000
    outfile_name = ""
    outfile_head = b''
    print("version:", version)
    log.write(version+'\n')
    if(argc == 1):
        generate_version_c('')
        exit(0)
    elif ((argc == 3) and argv[1] == "-v"):
        generate_version_c(argv[2])
        exit(0)
    elif ((argc == 3 or argc==4) and argv[1] == "-n"):
        opt = 1
        app_name = argv[2]
        if(argc == 4):
            outfile_name = argv[3]
    elif ((argc == 3 or argc==4) and argv[1] == "-u"):
        opt = 2
        app_name = argv[2]
        if(argc == 4):
            outfile_name = argv[3]
    elif ((argc == 5 or argc==6) and argv[1] == "-um"):
        opt = 3
        boot_name = argv[2]
        app_offset = literal_eval(argv[3])
        app_name = argv[4]
        if(argc == 6):
            outfile_name = argv[5]
    '''
    print("opt:", opt)
    print("boot_name:", boot_name)
    print("app_name:", app_name)
    print("app_offset: %X" % app_offset)
    print("outfile_name:", outfile_name)
    '''
    try:
        f = open(app_name, 'rb')
        data = f.read()
        f.close()
    except:
        print("%s open fail" % app_name)
        log.write(app_name+' open fail!!!\n')
        log.close()
        exit()

    if(opt > 0):
        magic = 0xAEAE
        encrypt_algo = 0
        rescv = 0
        header=b''
        #ISOTIMEFORMAT='%Y-%m-%d %X'
        #version = time.strftime( ISOTIMEFORMAT, time.localtime() )

        offset =  app_name.rindex(".")
        #print(". offset:", offset)
        suffix = app_name[offset:]
        #print(suffix)
        _middle_path=''
        _path=""
        if(outfile_name == ""):
            _middle_path=app_name[0:offset]
        else:
            offset=app_name.rindex("/")
            _middle_path=app_name[0:offset]+"/"+outfile_name
        
        if(opt == 1):
            _path = _middle_path+"_"+version+suffix
            fo = open(_path, "wb+")
            fo.write(data)
            fo.close()
            print("generate file : %s" % _path)
            log.write("generate file: "+_path +' success!\n')
        elif(opt >= 2):
            crc32 = zlib.crc32(data, 0) & 0xFFFFFFFF
            crc32 ^= 0xFFFFFFFF
            size = len(data)
            print('size: %d' % size)
            print('version: %s' % version)
            print('crc32: %08x' % crc32)
			
            _path = _middle_path+"_"+'app_upgrade_'+version+suffix
            header = struct.pack("<HBB24sLL", magic, encrypt_algo, rescv, version.encode("utf-8"), crc32, size)
            #print("header len: %s" % len(header))
            #print("header: %s" % header)
            fo = open(_path, "wb+")
            fo.write(header)
            fo.write(data)
            fo.close()
            print("generate application uprade file: %s success!" % _path)
            log.write("generate application uprade file: "+_path +' success!\n')
            if(opt == 3):
                try:
                    f = open(boot_name, 'rb')
                    boot_data = f.read()
                    f.close()
                    _path = _middle_path+"_"+'boot_app_'+version+suffix
                    fo = open(_path, "wb+")
                    fo.write(boot_data)
                    boot_len = len(boot_data)
                    #print('boot len=%d' % (boot_len))
                    #print('add xff len=%d' % (app_offset - boot_len))
                    for i in range(boot_len, app_offset):
                        fo.write(b'\xff')
                    fo.write(data)
                    fo.close()
                    print("generate boot and application merge file: %s success!" % _path)
                    log.write("generate boot and application merge file: "+_path +' success!\n')
                except:
                    print("%s open fail" % boot_name)
                    log.write(boot_name+" open fail\n")
                    log.close()
                    exit()
log.close()
exit()